package com.flashcash.kotlin.utils

import com.x.leo.apphelper.log.XLog
import java.util.concurrent.*

/**
 * @作者:XLEO
 * @创建日期: 2017/8/24 10:20
 * @描述:${TODO}
 *
 * @更新者:${Author}$
 * @更新时间:${Date}$
 * @更新描述:${TODO}
 * @下一步：
 */
object ThreadPoolManager {
    private val threadPool: ThreadPoolExecutor by lazy {
        val availableProcessors = if (Runtime.getRuntime().availableProcessors() > 1) {
            Runtime.getRuntime().availableProcessors()
        } else {
            3
        }
        val coreThreadNum:Int = if(availableProcessors <= 1){
            1
        }else{
            availableProcessors - 1
        }
        val maxThreadNum:Int = if (availableProcessors > 2){
            availableProcessors * 2 - 1
        }else{
            3
        }
        val capacity = if(availableProcessors > 3){
            availableProcessors * 3 + 1
        }else{
            10
        }
        ThreadPoolExecutor(coreThreadNum,
                maxThreadNum,
                10,
                TimeUnit.MINUTES,
                LinkedBlockingDeque<Runnable>(capacity),
                Executors.defaultThreadFactory(),
                LocalRejectHandler()
                )
    }



    fun runWithThread(runnable: Runnable) {
        threadPool.execute {
            try {
                runnable.run()
            }catch (e:Exception){
                if (runnable is RunnableWithBackPolicy) {
                    runnable.rollBack()
                }else{
                    XLog.e("runnable execute error:",e,100)
                }
            }
        }
    }
    fun runWithThread(block:()->Unit){
        threadPool.execute {
            block.invoke()
        }
    }
}

class LocalRejectHandler:RejectedExecutionHandler{
    override fun rejectedExecution(r: Runnable?, executor: ThreadPoolExecutor?) {
        if (r is RunnableWithBackPolicy) {
            r.rollBack()
        }else{
            throw RejectedExecutionException("Task " + r.toString() +
                    " rejected from " +
                    executor.toString())
        }
    }
}

abstract class RunnableWithBackPolicy:Runnable{
    abstract fun rollBack()
}